import java.util.*;

interface Cache{
    Object get(Object args);
    void put(Object args,Object res);
}


class LRUCache implements Cache{
    private Map<Object,Object> resMark;
    private int cacheSize;

    LRUCache(int cSize){
        resMark=new LinkedHashMap<>(cSize);
        cacheSize=cSize;
    }

    @Override
    public Object get(Object args){
        Object res = resMark.get(args);
        if(res!=null){
            resMark.remove(args);
            resMark.put(args,res);
        }
        return res;
    }

    @Override
    public void put(Object args,Object res){
        while(resMark.size()>=cacheSize){
            resMark.remove(resMark.keySet().iterator().next());
        }
        resMark.put(args, res);
    }
}

interface Function {
    Object run(List<Object> args,CacheFuncUtil util);
}


class CacheFuncUtil {

    private Cache cache;

    private Function runFunc;

    CacheFuncUtil(Cache usedCache,Function function){
        cache=usedCache;
        runFunc=function;
    }

    Object runCacheFunc(List<Object> args){
        Object res=cache.get(args);
        if(res==null){
            res=runFunc.run(args,this);
            cache.put(args,res);
        }
        return res;
    }
}

